package com.empire.module.system.controller.admin.auth;

import com.alibaba.fastjson.JSONObject;
import com.empire.framework.common.pkivo.*;
import com.empire.framework.security.core.service.PkiVerifyApiClient;
import com.empire.module.system.controller.admin.auth.vo.AuthLoginReqVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;

@Slf4j
@Validated
@RestController
public class PkiValidatorController {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public static final String USERNAME_KEY = "Username";
    public static final String SECURITY_KEY = "Security";
    public static final String PKI_TOKEN_KEY = "PKI_TOKEN";

    @PermitAll
    @RequestMapping(value = "/getCallbackUserName")
    public String getCallbackUserName(HttpSession session) {
        // 从Session中获取保存的头信息
        String username = (String)session.getAttribute(USERNAME_KEY);
        log.info("从Session中获取保存的头信息 username {}", username);
        return  username;
    }

    /**
     * pki登陆
     *
     * @param request 请求信息
     */
    @PermitAll
    @RequestMapping(value = "/token")
    public void token(HttpServletRequest request,
                      HttpServletResponse response) throws IOException {

        String userToken = request.getHeader("RZZX-USERTOKEN");
        String appToken = request.getHeader("RZZX-APPTOKEN");

        // 2.1.1 用户令牌核验
        TokenVerifyApiResponse result = PkiVerifyApiClient.callTokenVerifyApi(
                appToken, userToken, userToken);
        if ("0000".equals(result.getStatus_code())) {
            System.out.println("令牌核验成功：" + result.getMessage());
            // 执行成功逻辑（如允许用户操作）
        } else {
            System.out.println("令牌核验失败：" + result.getMessage());
            // 执行失败逻辑（如拒绝操作、提示用户重新登录）
        }

        // 2.1.2 用户令牌信息获取
        UserTokenInfoResponse userTokenInfo = PkiVerifyApiClient.getUserTokenInfo(
                appToken, userToken, userToken);
        if ("0000".equals(userTokenInfo.getStatus_code())) {
            System.out.println("令牌信息成功：" + JSONObject.toJSONString(userTokenInfo.getResult()));
            // 执行成功逻辑（如允许用户操作）
        } else {
            System.out.println("令牌获取失败：" + result.getMessage());
            // 执行失败逻辑（如拒绝操作、提示用户重新登录）
        }

        // 2.1.6 用户信息查询
        UserInfoQueryRequest queryRequest = new UserInfoQueryRequest();
        queryRequest.setPId(userTokenInfo.getResult().getPid());
        UserInfoQueryResponse userInfo = PkiVerifyApiClient.getUserInfo(
                appToken, userToken, queryRequest);
        if ("0000".equals(userInfo.getStatus_code())) {
            System.out.println("用户信息查询成功：" + JSONObject.toJSONString(userInfo.getResult()));
            // 执行成功逻辑（如允许用户操作）
        } else {
            System.out.println("用户信息查询失败：" + result.getMessage());
            // 执行失败逻辑（如拒绝操作、提示用户重新登录）
        }

        UserInfoQueryResult userInfoResult = userInfo.getResult();
        if (userInfoResult != null && userInfoResult.getRows() != null && !userInfoResult.getRows().isEmpty()) {
            List<UserInfoRow> rows = userInfoResult.getRows();
            UserInfoRow user = rows.getFirst();
            AuthLoginReqVO reqVO = new AuthLoginReqVO();
            reqVO.setUsername(user.getIdcard());
            reqVO.setPassword("123456");
            log.info("用户登陆：username={}, password={}", user.getIdcard(), reqVO.getPassword());
            // 3. 重定向到前端 index.html（或返回 200，由前端跳转）
            try {
                String idCard = user.getIdcard(); // 从用户信息中获取身份证号
                // 4.1. 认证成功 把身份证写入前端
                Cookie cookie = new Cookie(USERNAME_KEY, idCard); // 实际应存用户标识（如 userId）
                cookie.setPath("/"); // Cookie 作用域为根路径，确保前端能获取
                cookie.setMaxAge(Integer.MAX_VALUE); // Cookie 有效期（秒）
                response.addCookie(cookie);

                // 4.2 新增存储 userToken 的 Cookie（名称为 Security）
                Cookie securityCookie = new Cookie(SECURITY_KEY, userToken); // 键为 Security，值为 userToken
                securityCookie.setPath("/"); // 作用域同用户名 Cookie，确保同域可访问
                securityCookie.setMaxAge(Integer.MAX_VALUE); // 与用户名 Cookie 保持相同有效期
                // 建议对 token 开启 HttpOnly 和 Secure（增强安全性）
                // securityCookie.setHttpOnly(true); // 防止 JS 读取，降低 XSS 风险
                // securityCookie.setSecure(true); // 生产环境若用 HTTPS，建议开启
                response.addCookie(securityCookie);

                String key = SECURITY_KEY + "::" + idCard;
                stringRedisTemplate.opsForValue().set(key, userToken);

                // 存储刷新令牌所需要的信息
                PkiVerifyApiClient.verifyAppToken(appToken, userToken, appToken);
                AppTokenInfoResponse appTokenInfo = PkiVerifyApiClient.getAppTokenInfo(appToken, userToken, appToken);
                FullTokenOperateRequest refreshTokenRequest = new FullTokenOperateRequest();
                refreshTokenRequest.setAppToken(appToken);
                refreshTokenRequest.setUserToken(userToken);
                refreshTokenRequest.setType("user");
                refreshTokenRequest.setTokenId(userToken);

                refreshTokenRequest.setCalledId("cli");
                refreshTokenRequest.setCallerNounce(UUID.randomUUID().toString().replaceAll("-", ""));
                refreshTokenRequest.setCallerSign(appTokenInfo.getResult().getSign());
                refreshTokenRequest.setCallerTimestamp(appTokenInfo.getResult().getExpireAt());

                String tokenKey = PKI_TOKEN_KEY + "::" + idCard;
                stringRedisTemplate.opsForValue().set(tokenKey, JSONObject.toJSONString(refreshTokenRequest));
                log.info("记录登陆信息到redis: {}", JSONObject.toJSONString(refreshTokenRequest));

                // 重定向到登录页，并携带身份证号参数
                response.sendRedirect("/AutoLogin");
            } catch (IOException e) {
                e.printStackTrace();
                response.setStatus(500);
            }
        }
    }
}
